package com.px.user.controller;


import com.px.common.core.RespCode;
import com.px.common.core.Response;
import com.px.user.entity.ChargeMoney;
import com.px.user.entity.Withdraw;
import com.px.user.mapper.ChargeMoneyMapper;
import com.px.user.mapper.WithdrawMapper;
import com.px.user.model.*;
import com.px.user.service.WithdrawService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Min;
import java.math.BigDecimal;
import java.security.Principal;
import java.sql.Timestamp;
import java.util.Collection;


@Slf4j
@Validated
@RestController
@RequestMapping("/money")
@Api(value = "充值提现管理", tags = {"充值提现管理"})
public class WithdrawController {

    @Autowired
    private WithdrawService withdrawService;

    @Autowired
    private ChargeMoneyMapper chargeMoneyMapper;

    @Autowired
    private WithdrawMapper withdrawMapper;

    @PostMapping("/chargeManual")
    @PreAuthorize("hasAnyAuthority('ADMIN')")
    @ApiOperation(value = "人工充值", authorizations = {@Authorization(value = "token")}, tags = {"充值"})
    public Response chargeManualPost(
            @Validated(ActionModel.Insert.class) @RequestBody ChargeMoney chargeMoney,
            Principal principal) {
        if (chargeMoney.getUserId() == null)
            return Response.fail(RespCode.PARA_ERROR, "请设置充值对象");
        if (chargeMoney.getMoney().compareTo(BigDecimal.valueOf(0)) <= 0)
            return Response.fail(RespCode.PARA_ERROR, "充值金额不能小于0");
        withdrawService.chargeManual(chargeMoney);
        log.info(String.format("%s charge for %s: %s", principal.getName(), chargeMoney.getUserId(), chargeMoney.getMoney()));
        return Response.success(null);
    }

    @PostMapping("/charge")
    @ApiOperation(value = "在线充值", authorizations = {@Authorization(value = "token")}, tags = {"充值"})
    public Response<PayRespModel.InnerData> chargePost(
            @Validated(ActionModel.Insert.class) @RequestBody ChargeMoney chargeMoney,
            Principal principal) throws IllegalAccessException {
        chargeMoney.setUserId(Long.valueOf(principal.getName()));
        PayRespModel.InnerData data = withdrawService.charge(chargeMoney);
        if (data == null)
            return Response.fail(RespCode.PAY_CHANNEL_ERROR, null);
        return Response.success(data);
    }

    @GetMapping("/charge")
    @ApiOperation(value = "充值记录", authorizations = {@Authorization(value = "token")}, tags = {"充值"})
    public Response<PagingResp<ChargeMoney>> chargeGet(
            @ApiParam(value = "用户ID(管理员使用)", example = "1") @RequestParam(value = "userId", required = false) Long userId,
            @ApiParam(value = "开始时间", example = "1566805792293") @RequestParam(value = "startTime", required = false) Long startTime,
            @ApiParam(value = "截止时间", example = "1566805792293") @RequestParam(value = "endTime", required = false) Long endTime,
            @ApiParam(value = "充值渠道: 支付宝,微信,云闪付,银联,人工", example = "支付宝") @RequestParam(value = "channel", required = false) String channel,
            @ApiParam(value = "状态筛选(CHARGING,CHARGING_FAIL,FAIL,SUCCESS)", example = "SUCCESS") @RequestParam(value = "status", required = false) String status,
            @ApiParam(value = "排序字段(倒序)", example = "updateTime") @RequestParam(value = "orderField", required = false, defaultValue = "createTime") String orderField,
            @ApiParam(value = "页码", example = "0") @RequestParam(value = "page", required = false, defaultValue = "0") @Min(0) Integer page,
            @ApiParam(value = "返回数量", example = "10") @RequestParam(value = "limit", required = false, defaultValue = "10") @Min(1) Integer limit,
            Authentication authentication) {
        ChargeMoney qChargeMoney =
                ChargeMoney.builder()
                        .userId(userId)
                        .startTime(startTime == null ? null : new Timestamp(startTime))
                        .endTime(endTime == null ? null : new Timestamp(endTime))
                        .status(status)
                        .channel(channel)
                        .orderField(orderField)
                        .startIndex(page * limit)
                        .limit(limit)
                        .build();

        Collection roles = authentication.getAuthorities();
        SimpleGrantedAuthority admin = new SimpleGrantedAuthority("ADMIN");
        if (!roles.contains(admin))
            qChargeMoney.setUserId(Long.valueOf(authentication.getName()));

        return Response.success(PagingResp.<ChargeMoney>builder()
                .itemCount(chargeMoneyMapper.pagingCount(qChargeMoney))
                .items(chargeMoneyMapper.paging(qChargeMoney))
                .build());
    }

    @PutMapping("/charge")
    @PreAuthorize("hasAnyAuthority('ADMIN')")
    @ApiOperation(value = "充值状态修改", authorizations = {@Authorization(value = "token")}, tags = {"充值"})
    public Response chargePut(
            @Validated(ActionModel.Update.class) @RequestBody ChargeMoney chargeMoney, Principal principal) {
        log.info(principal.getName() + " 修改充值订单状态到: " + chargeMoney.getStatus());
        chargeMoneyMapper.updateStatus(chargeMoney);
        return Response.success(null);
    }

    @PostMapping("/charge/res")
    @ApiOperation(value = "充值结果", tags = {"充值"})
    public String chargeResultPost(
            @Validated(ActionModel.Update.class) @RequestBody PayBackModel payBackModel) throws IllegalAccessException {
        if (payBackModel.getSignature() == null || payBackModel.getOrderId() == null) {
            log.error("error call: " + payBackModel.toString());
            return "FAIL";
        }
        String sig = withdrawService.md5Signature(payBackModel);
        if (!sig.equals(payBackModel.getSignature())) {
            log.error("error signature: " + payBackModel.toString()+",target:"+sig);
            return "FAIL";
        }
        if (payBackModel.getPayResult() == 2)
            withdrawService.chargeResult(ChargeMoney.builder()
                    .status(MoneyStatus.SUCCESS.getStatus())
                    .id(Long.valueOf(payBackModel.getOrderId()))
                    .money(BigDecimal.valueOf(payBackModel.getAmount()))
                    .channel(payBackModel.getPayType())
                    .build());
        return "SUCCESS";
    }

    @PostMapping("/withdraw")
    @Validated(ActionModel.Insert.class)
    @ApiOperation(value = "提现申请", authorizations = {@Authorization(value = "token")}, tags = {"提现"})
    public Response withdrawPost(
            @Validated(ActionModel.Insert.class) @RequestBody Withdraw withdraw, Principal principal) {
        if (withdraw.getMoney().equals(BigDecimal.valueOf(0)))
            return Response.fail(RespCode.PARA_ERROR, "金额不能等于0");
        withdraw.setUserId(Long.valueOf(principal.getName()));
        return withdrawService.withdraw(withdraw);
    }

    @GetMapping("/withdraw")
    @ApiOperation(value = "提现记录", authorizations = {@Authorization(value = "token")}, tags = {"提现"})
    public Response<PagingResp<Withdraw>> withdrawGet(
            @ApiParam(value = "用户ID(管理员使用)", example = "1") @RequestParam(value = "userId", required = false) Long userId,
            @ApiParam(value = "开始时间", example = "1566805792293") @RequestParam(value = "startTime", required = false) Long startTime,
            @ApiParam(value = "截止时间", example = "1566805792293") @RequestParam(value = "endTime", required = false) Long endTime,
            @ApiParam(value = "状态筛选(AUDITING,AUDIT_FAIL,FAIL,SUCCESS)", example = "SUCCESS") @RequestParam(value = "status", required = false) String status,
            @ApiParam(value = "排序字段(倒序)", example = "updateTime") @RequestParam(value = "orderField", required = false, defaultValue = "createTime") String orderField,
            @ApiParam(value = "页码", example = "0") @RequestParam(value = "page", required = false, defaultValue = "0") @Min(0) Integer page,
            @ApiParam(value = "返回数量", example = "10") @RequestParam(value = "limit", required = false, defaultValue = "10") @Min(1) Integer limit,
            Authentication authentication) {
        Withdraw qWithdraw =
                Withdraw.builder()
                        .userId(userId)
                        .startTime(startTime == null ? null : new Timestamp(startTime))
                        .endTime(endTime == null ? null : new Timestamp(endTime))
                        .status(status)
                        .orderField(orderField)
                        .startIndex(page * limit)
                        .limit(limit)
                        .build();

        Collection roles = authentication.getAuthorities();
        SimpleGrantedAuthority admin = new SimpleGrantedAuthority("ADMIN");
        if (!roles.contains(admin))
            qWithdraw.setUserId(Long.valueOf(authentication.getName()));

        return Response.success(PagingResp.<Withdraw>builder()
                .itemCount(withdrawMapper.pagingCount(qWithdraw))
                .items(withdrawMapper.paging(qWithdraw))
                .build());
    }

    @PutMapping("/withdraw")
    @PreAuthorize("hasAnyAuthority('ADMIN')")
    @ApiOperation(value = "提现处理", authorizations = {@Authorization(value = "token")}, tags = {"提现"})
    public Response withdrawPut(
            @Validated(ActionModel.Update.class) @RequestBody Withdraw withdraw, Principal principal) {
        log.info(principal.getName() + " change withdraw status to: " + withdraw.getStatus());
        withdrawService.withdrawUpdate(withdraw);
        return Response.success(null);
    }
}
